package cn.walls1717.juc.jmm;

import lombok.extern.slf4j.Slf4j;

/**
 * volatile的测试
 *
 * @author walls1717
 * @since 2022/12/11 1:04
 **/
@Slf4j
public class VolatileDemo {

    /**
     * 为什么会出现可见性？<br>
     * 因为线程读内存中的变量时，会先将变量的副本拷贝到线程的本地内存中，操作本地内存的副本变量，这时，线程将本地内存中的
     * 变量副本进行了修改，但是没有及时的将数据写回主内存中；另外一个线程从主内存中拿到的还是老数据，同样是拷贝的变量副本。<br><br>
     *
     * volatile怎么保证可见性？<br>
     * 使用volatile修饰的变量，在被修改时会立即将最新值写入到内存中。
     * 在读取值时，会直接从内存中获取最新值。从而保证了可见性。<br><br>
     *
     * volatile怎么保证有序性？<br>
     * 保证有序性就是禁止指令重排，那么什么是指令重排？指令重排就是编译器和处理器为了优化程序性能而对指令序列进行重新排序的手段，
     * 这种指令重拍并不会影响程序最终的结果，也就是说在不影响最终结果的情况下，才有可能会发生指令重排。<br>
     * volatile通过加内存屏障来保证有序性，内存屏障之前的所有写操作都要回写到主内存；
     * 内存屏障之后的所有读操作都要获得内存屏障之前所有写操作的最新结果。<br><br>
     *
     * volatile能保证原子性吗？<br>
     * volatile不能保证原子性，举个简单的例子，比如i++操作，i++在底层是分为三步的：获取值，计算值，赋值。
     * 这时候第一个线程正在刚计算完值，值为2，还没来得及赋值，另一个线程进来获取值，获取到的还是旧值1，这是线程1执行赋值操作，
     * 将新值2写回，但是线程2操作的仍然是旧值1，将旧值1加1再写回，结果还是2覆盖了。<br>
     *
     */
    volatile int age;

    public static void main(String[] args) {

    }
}
